home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / bash_114.zip / bash-1.14.2 / getcwd.c < prev    next >
C/C++ Source or Header  |  1993-12-19  |  8KB  |  345 lines

  1. /* getcwd.c -- stolen from the GNU C library and modified to work with bash. */
  2.  
  3. /* Copyright (C) 1991 Free Software Foundation, Inc.
  4.    This file is part of the GNU C Library.
  5.  
  6.    The GNU C Library is free software; you can redistribute it and/or
  7.    modify it under the terms of the GNU Library General Public License as
  8.    published by the Free Software Foundation; either version 2 of the
  9.    License, or (at your option) any later version.
  10.  
  11.    The GNU C Library is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.    Library General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU Library General Public
  17.    License along with the GNU C Library; see the file COPYING.LIB.  If
  18.    not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  19.    Cambridge, MA 02139, USA.  */
  20.  
  21. #include "bashtypes.h"
  22. #include <errno.h>
  23.  
  24. #if defined (HAVE_LIMITS_H)
  25. #  include <limits.h>
  26. #endif
  27.  
  28. #if defined (HAVE_DIRENT_H)
  29. #  include <dirent.h>
  30. #else
  31. #  include <sys/dir.h>
  32. #  if !defined (dirent)
  33. #    define dirent direct
  34. #  endif /* !dirent */
  35. #endif /* !HAVE_DIRENT_H */
  36.  
  37. #if defined (HAVE_UNISTD_H)
  38. #  include <unistd.h>
  39. #endif
  40.  
  41. #include "posixstat.h"
  42. #include "maxpath.h"
  43. #include "config.h"
  44.  
  45. #if defined (HAVE_STDLIB_H)
  46. #  include <stdlib.h>
  47. #else
  48. #  include "ansi_stdlib.h"
  49. #endif /* !HAVE_STDLIB_H */
  50.  
  51. #if defined (HAVE_STRING_H)
  52. #  include <string.h>
  53. #else
  54. #  include <strings.h>
  55. #endif /* !HAVE_STRING_H */
  56.  
  57. /* Not all systems declare ERRNO in errno.h... and some systems #define it! */
  58. #if !defined (errno)
  59. extern int errno;
  60. #endif /* !errno */
  61.  
  62. #if defined (__STDC__)
  63. #  define CONST const
  64. #  define PTR void *
  65. #else /* !__STDC__ */
  66. #  define CONST
  67. #  define PTR char *
  68. #endif /* !__STDC__ */
  69.  
  70. #if !defined (PATH_MAX)
  71. #  if defined (MAXPATHLEN)
  72. #    define PATH_MAX MAXPATHLEN
  73. #  else /* !MAXPATHLEN */
  74. #    define PATH_MAX 1024
  75. #  endif /* !MAXPATHLEN */
  76. #endif /* !PATH_MAX */
  77.  
  78. #if defined (_POSIX_VERSION) || defined (USGr3) || defined (HAVE_DIRENT_H)
  79. #  if !defined (HAVE_DIRENT)
  80. #    define HAVE_DIRENT
  81. #  endif /* !HAVE_DIRENT */
  82. #endif /* _POSIX_VERSION || USGr3 || HAVE_DIRENT_H */
  83.  
  84. #if defined (HAVE_DIRENT)
  85. #  define D_NAMLEN(d)    (strlen ((d)->d_name))
  86. #else
  87. #  define D_NAMLEN(d)    ((d)->d_namlen)
  88. #endif /* ! (_POSIX_VERSION || USGr3) */
  89.  
  90. #if defined (USG) || defined (USGr3)
  91. #  define d_fileno d_ino
  92. #endif
  93.  
  94. #if !defined (alloca)
  95. extern char *alloca ();
  96. #endif /* alloca */
  97.  
  98. /* Heuristic to tell whether or not the current machine has lstat(2).
  99.    Can probably be fooled easily. */
  100. #if !defined (S_ISLNK)
  101. #  define lstat stat
  102. #endif
  103.  
  104. /* Get the pathname of the current working directory,
  105.    and put it in SIZE bytes of BUF.  Returns NULL if the
  106.    directory couldn't be determined or SIZE was too small.
  107.    If successful, returns BUF.  In GNU, if BUF is NULL,
  108.    an array is allocated with `malloc'; the array is SIZE
  109.    bytes long, unless SIZE <= 0, in which case it is as
  110.    big as necessary.  */
  111. #if defined (__STDC__)
  112. char *
  113. getcwd (char *buf, size_t size)
  114. #else /* !__STDC__ */
  115. char *
  116. getcwd (buf, size)
  117.      char *buf;
  118.      size_t size;
  119. #endif /* !__STDC__ */
  120. {
  121.   static CONST char dots[]
  122.     = "../../../../../../../../../../../../../../../../../../../../../../../\
  123. ../../../../../../../../../../../../../../../../../../../../../../../../../../\
  124. ../../../../../../../../../../../../../../../../../../../../../../../../../..";
  125.   CONST char *dotp, *dotlist;
  126.   size_t dotsize;
  127.   dev_t rootdev, thisdev;
  128.   ino_t rootino, thisino;
  129.   char path[PATH_MAX + 1];
  130.   register char *pathp;
  131.   char *pathbuf;
  132.   size_t pathsize;
  133.   struct stat st;
  134.  
  135.   if (buf != NULL && size == 0)
  136.     {
  137.       errno = EINVAL;
  138.       return ((char *)NULL);
  139.     }
  140.  
  141.   pathsize = sizeof (path);
  142.   pathp = &path[pathsize];
  143.   *--pathp = '\0';
  144.   pathbuf = path;
  145.  
  146.   if (stat (".", &st) < 0)
  147.     return ((char *)NULL);
  148.   thisdev = st.st_dev;
  149.   thisino = st.st_ino;
  150.  
  151.   if (stat ("/", &st) < 0)
  152.     return ((char *)NULL);
  153.   rootdev = st.st_dev;
  154.   rootino = st.st_ino;
  155.  
  156.   dotsize = sizeof (dots) - 1;
  157.   dotp = &dots[sizeof (dots)];
  158.   dotlist = dots;
  159.   while (!(thisdev == rootdev && thisino == rootino))
  160.     {
  161.       register DIR *dirstream;
  162.       register struct dirent *d;
  163.       dev_t dotdev;
  164.       ino_t dotino;
  165.       char mount_point;
  166.       int namlen;
  167.  
  168.       /* Look at the parent directory.  */
  169.       if (dotp == dotlist)
  170.     {
  171.       /* My, what a deep directory tree you have, Grandma.  */
  172.       char *new;
  173.       if (dotlist == dots)
  174.         {
  175.           new = malloc (dotsize * 2 + 1);
  176.           if (new == NULL)
  177.         goto lose;
  178.           memcpy (new, dots, dotsize);
  179.         }
  180.       else
  181.         {
  182.           new = realloc ((PTR) dotlist, dotsize * 2 + 1);
  183.           if (new == NULL)
  184.         goto lose;
  185.         }
  186.       memcpy (&new[dotsize], new, dotsize);
  187.       dotp = &new[dotsize];
  188.       dotsize *= 2;
  189.       new[dotsize] = '\0';
  190.       dotlist = new;
  191.     }
  192.  
  193.       dotp -= 3;
  194.  
  195.       /* Figure out if this directory is a mount point.  */
  196.       if (stat (dotp, &st) < 0)
  197.     goto lose;
  198.       dotdev = st.st_dev;
  199.       dotino = st.st_ino;
  200.       mount_point = dotdev != thisdev;
  201.  
  202.       /* Search for the last directory.  */
  203.       dirstream = opendir (dotp);
  204.       if (dirstream == NULL)
  205.     goto lose;
  206.       while ((d = readdir (dirstream)) != NULL)
  207.     {
  208.       if (d->d_name[0] == '.' &&
  209.           (d->d_name[1] == '\0' ||
  210.         (d->d_name[1] == '.' && d->d_name[2] == '\0')))
  211.         continue;
  212.       if (mount_point || d->d_fileno == thisino)
  213.         {
  214.           char *name;
  215.  
  216.           namlen = D_NAMLEN(d);
  217.           name = (char *)
  218.         alloca (dotlist + dotsize - dotp + 1 + namlen + 1);
  219.           memcpy (name, dotp, dotlist + dotsize - dotp);
  220.           name[dotlist + dotsize - dotp] = '/';
  221.           memcpy (&name[dotlist + dotsize - dotp + 1],
  222.               d->d_name, namlen + 1);
  223.           if (lstat (name, &st) < 0)
  224.         {
  225.           int save = errno;
  226.           (void) closedir (dirstream);
  227.           errno = save;
  228.           goto lose;
  229.         }
  230.           if (st.st_dev == thisdev && st.st_ino == thisino)
  231.         break;
  232.         }
  233.     }
  234.       if (d == NULL)
  235.     {
  236.       int save = errno;
  237.       (void) closedir (dirstream);
  238.       errno = save;
  239.       goto lose;
  240.     }
  241.       else
  242.     {
  243.       size_t space;
  244.  
  245.       while ((space = pathp - pathbuf) <= namlen)
  246.         {
  247.           char *new;
  248.  
  249.           if (pathbuf == path)
  250.         {
  251.           new = malloc (pathsize * 2);
  252.           if (!new)
  253.             goto lose;
  254.         }
  255.           else
  256.         {
  257.           new = realloc ((PTR) pathbuf, (pathsize * 2));
  258.           if (!new)
  259.             goto lose;
  260.           pathp = new + space;
  261.         }
  262.           (void) memcpy (new + pathsize + space, pathp, pathsize - space);
  263.           pathp = new + pathsize + space;
  264.           pathbuf = new;
  265.           pathsize *= 2;
  266.         }
  267.  
  268.       pathp -= namlen;
  269.       (void) memcpy (pathp, d->d_name, namlen);
  270.       *--pathp = '/';
  271.       (void) closedir (dirstream);
  272.     }
  273.  
  274.       thisdev = dotdev;
  275.       thisino = dotino;
  276.     }
  277.  
  278.   if (pathp == &path[sizeof(path) - 1])
  279.     *--pathp = '/';
  280.  
  281.   if (dotlist != dots)
  282.     free ((PTR) dotlist);
  283.  
  284.   {
  285.     size_t len = pathbuf + pathsize - pathp;
  286.     if (buf == NULL)
  287.       {
  288.     if (len < (size_t) size)
  289.       len = size;
  290.     buf = (char *) malloc (len);
  291.     if (buf == NULL)
  292.       goto lose2;
  293.       }
  294.     else if ((size_t) size < len)
  295.       {
  296.     errno = ERANGE;
  297.     goto lose2;
  298.       }
  299.     (void) memcpy((PTR) buf, (PTR) pathp, len);
  300.   }
  301.  
  302.   if (pathbuf != path)
  303.     free (pathbuf);
  304.  
  305.   return (buf);
  306.  
  307.  lose:
  308.   if ((dotlist != dots) && dotlist)
  309.     {
  310.       int e = errno;
  311.       free ((PTR) dotlist);
  312.       errno = e;
  313.     }
  314.  
  315.  lose2:
  316.   if ((pathbuf != path) && pathbuf)
  317.     {
  318.       int e = errno;
  319.       free ((PTR) pathbuf);
  320.       errno = e;
  321.     }
  322.   return ((char *)NULL);
  323. }
  324.  
  325. #if defined (TEST)
  326. #  include <stdio.h>
  327. main (argc, argv)
  328.      int argc;
  329.      char **argv;
  330. {
  331.   char b[PATH_MAX];
  332.  
  333.   if (getcwd(b, sizeof(b)))
  334.     {
  335.       printf ("%s\n", b);
  336.       exit (0);
  337.     }
  338.   else
  339.     {
  340.       perror ("cwd: getcwd");
  341.       exit (1);
  342.     }
  343. }
  344. #endif /* TEST */
  345.